6432
2820
J'écris actuellement un analyseur de base pour une saveur XML. En guise d'exercice, j'implémente un analyseur basé sur une table LL.
Voici mon exemple de grammaire BNF:
% chaîne de données de nom de jeton
%% / * LL (1) * /
doc: elem
elem: "<" open_tag
open_tag: nom attr close_tag
close_tag: ">" elem_or_data ""
| "/>"
;
elem_or_data: "<" open_tag elem_or_data
| données elem_or_data
| / * epsilon * /
;
attr: nom ":" chaîne attr
| / * epsilon * /
;
Cette grammaire est-elle correcte?
Chaque littéral terminal est entre guillemets. Les terminaux abstraits sont spécifiés par% token.
Je code un lexer écrit à la main pour convertir mon entrée en une liste de jetons. Comment pourrais-je tokeniser les terminaux abstraits? 
L'approche classique serait d'écrire une expression régulière (ou autre outil de reconnaissance) pour chaque terminal possible.
Ce que vous appelez des terminaux "abstraits", qui sont parfaitement concrets, sont en fait des terminaux dont les modèles associés reconnaissent plus d'une chaîne d'entrée possible. La chaîne réellement reconnue (ou une fonction calculée de cette chaîne) doit être transmise à l'analyseur en tant que valeur sémantique du jeton.
Nominalement, à chaque point de la chaîne d'entrée, le tokeniseur exécutera tous les programmes de reconnaissance et choisira celui avec la correspondance la plus longue. (Il s'agit de la règle dite de "munch maximal".) Cela peut généralement être optimisé, en particulier si tous les modèles sont des expressions régulières. (F) lex fera cette optimisation pour vous, par exemple.
Une complication dans votre cas est que la tokenisation de votre langage dépend du contexte. En particulier, lorsque la cible est elem_or_data, les seuls jetons possibles sont <,